#include "RingQueue.h"


RingQueue::RingQueue(long long size) :
    m_buffer(std::vector<unsigned char>(size)),
    m_wpos(0), m_rpos(0),
    m_size(size) {
    m_remain = size;
}

RingQueue::~RingQueue() {}

long long RingQueue::readData(unsigned char *data, long long maxlen)
{
    std::lock_guard<std::mutex> lck(m_mutex);

    if (maxlen > m_size || (m_size - m_remain) < maxlen) {
        return 0;
    }

    if (m_rpos + maxlen < m_size) {
        memcpy(data, m_buffer.data() + m_rpos, maxlen);
        m_rpos += maxlen;
        m_remain += maxlen;
    }
    else {
        int remain = m_size - m_rpos;
        memcpy(data, m_buffer.data() + m_rpos, remain);
        m_rpos = (m_rpos + remain) % m_size;
        memcpy(data + remain, m_buffer.data() + m_rpos, maxlen - remain);
        m_rpos += maxlen - remain;
        m_remain += maxlen;
    }
    return maxlen;
}


long long RingQueue::writeData(const unsigned char *data, long long len)
{
    std::lock_guard<std::mutex> loker(m_mutex);
    if (len > m_size || m_remain < len) {
        return 0;
    }

    if (m_wpos + len < m_size) {
        memcpy(m_buffer.data() + m_wpos, data, len);
        m_wpos = m_wpos + len;
        m_remain -= len;
    }
    else {
        int remain = m_size - m_wpos;
        memcpy(m_buffer.data() + m_wpos, data, remain);
        m_wpos = (m_wpos + remain) % m_size;
        memcpy(m_buffer.data() + m_wpos, data + remain, len - remain);
        m_wpos += (len - remain);
        m_remain -= len;
    }

    return len;
}
